package com.gpframework.common.weixin.common.util;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.gpframework.common.constant.CacheConstants;
import com.gpframework.common.constant.WeiXinConstants;
import com.gpframework.common.core.redis.RedisCache;
import com.gpframework.common.exception.BaseException;
import com.gpframework.common.utils.http.HttpUtils;
import com.gpframework.common.weixin.common.bean.WeChatInfo;
import com.gpframework.common.weixin.common.bean.WeiXinOauth2Token;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;

/**
 * 公众平台通用接口工具类
 *
 * @author zcl
 */
@Component
public class WeixinUtil {
    private static Logger logger = LoggerFactory.getLogger(WeixinUtil.class);

    /**
     * redis缓存
     */
    private static RedisCache redisCacheUtil;

    @Autowired
    private RedisCache redisCache;

    /**
     * 静态注入
     */
    @PostConstruct
    public void init() {
        WeixinUtil.redisCacheUtil = this.redisCache;
    }

    /**
     * 获取access_token
     *
     * @param JSCODE
     * @param appId
     * @param appSecret
     * @return
     */
    public static WeChatInfo getWxloginOpenId(String JSCODE, String appId, String appSecret) {
        logger.info("----" + JSCODE + "----");
        String requestUrl = WeiXinConstants.ACCESS_OAUTH3_URL.replace("APPID", appId).replace("APPSECRET", appSecret).replace("JSCODE", JSCODE);
        String rspStr = HttpUtils.sendGet(requestUrl, "GET", "utf-8");
        logger.info("小程序登录：" + rspStr);
        return JSONUtil.toBean(rspStr, WeChatInfo.class);
    }

    /**
     * 获取access_token
     *
     * @param appId     凭证
     * @param appSecret 密钥
     * @return
     */
    public static AccessToken getAccessToken(String appId, String appSecret) {
        AccessToken accessToken = null;
        //获取缓存
        String token = redisCacheUtil.getCacheObject(CacheConstants.ACCESS_TOKEN);
        if (!StringUtils.isEmpty(token)) {
            accessToken = new AccessToken();
            accessToken.setAccess_token(token);
            //缓存过期时间
            Long expire = redisCacheUtil.getExpire(CacheConstants.ACCESS_TOKEN);
            if (expire != null) {
                accessToken.setExpires_in(expire.intValue());
            }
            return accessToken;
        }
        String requestUrl = WeiXinConstants.ACCESS_TOKEN_URL.replace("APPID", appId).replace("APPSECRET", appSecret);
        String requestStr = HttpUtil.get(requestUrl);
        if (!StringUtils.isEmpty(requestStr)) {
            accessToken = JSONUtil.toBean(requestStr, AccessToken.class);
            //设置缓存
            redisCacheUtil.setCacheObject(CacheConstants.ACCESS_TOKEN, accessToken.getAccess_token());
            //设置有效时间
            int seconds = accessToken.getExpires_in() - 20;
            redisCacheUtil.expire(CacheConstants.ACCESS_TOKEN, seconds, TimeUnit.SECONDS);
        }
        // 如果请求成功
        return accessToken;
    }

    /**
     * 获取品牌的access_token
     *
     * @param brandId   品牌id
     * @param wxType    类型
     * @param appId     凭证
     * @param appSecret 密钥
     * @return
     */
    public static AccessToken getBrandAccessToken(Long brandId, String wxType, String appId, String appSecret) {
        if (StringUtils.isEmpty(brandId)) {
            throw new BaseException("品牌id不能为空");
        }
        AccessToken accessToken = null;
        //缓存key
        String key = CacheConstants.BRAND_ACCESS_TOKEN + wxType + brandId;
        //获取缓存
        String token = redisCacheUtil.getCacheObject(key);
        if (!StringUtils.isEmpty(token)) {
            accessToken = new AccessToken();
            accessToken.setAccess_token(token);
            //缓存过期时间
            Long expire = redisCacheUtil.getExpire(key);
            if (expire != null) {
                accessToken.setExpires_in(expire.intValue());
            }
            return accessToken;
        }
        //请求获取access_token
        String requestUrl = WeiXinConstants.ACCESS_TOKEN_URL.replace("APPID", appId).replace("APPSECRET", appSecret);
        String requestStr = HttpUtil.get(requestUrl);
        if (!StringUtils.isEmpty(requestStr)) {
            accessToken = JSONUtil.toBean(requestStr, AccessToken.class);
            if (accessToken.getErrcode() != null) {
                logger.error(requestStr);
                throw new BaseException("获取微信Token失败");
            }
            //设置缓存
            redisCacheUtil.setCacheObject(key, accessToken.getAccess_token());
            //设置有效时间
            int seconds = accessToken.getExpires_in() - 20;
            redisCacheUtil.expire(key, seconds, TimeUnit.SECONDS);
        }
        // 如果请求成功
        return accessToken;
    }

    /**
     * 重置品牌的access_token
     *
     * @param brandId   品牌id
     * @param wxType    类型
     * @param appId     凭证
     * @param appSecret 密钥
     * @return
     */
    public static AccessToken resetBrandAccessToken(Long brandId, String wxType, String appId, String appSecret) {
        if (StringUtils.isEmpty(brandId)) {
            throw new BaseException("品牌id不能为空");
        }
        AccessToken accessToken = null;
        //缓存key
        String key = CacheConstants.BRAND_ACCESS_TOKEN + wxType + brandId;
        //请求获取access_token
        String requestUrl = WeiXinConstants.ACCESS_TOKEN_URL.replace("APPID", appId).replace("APPSECRET", appSecret);
        String requestStr = HttpUtil.get(requestUrl);
        if (!StringUtils.isEmpty(requestStr)) {
            accessToken = JSONUtil.toBean(requestStr, AccessToken.class);
            if (accessToken.getErrcode() != null) {
                logger.error(requestStr);
                throw new BaseException("获取微信Token失败");
            }
            //设置缓存
            redisCacheUtil.setCacheObject(key, accessToken.getAccess_token());
            //设置有效时间
            int seconds = accessToken.getExpires_in() - 20;
            redisCacheUtil.expire(key, seconds, TimeUnit.SECONDS);
        }
        // 如果请求成功
        return accessToken;
    }

    /**
     * 获取登录
     *
     * @param appId
     * @param appSecret
     * @param code
     * @return
     */
    public static WeiXinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
        String requestUrl = String.format(WeiXinConstants.ACCESS_OAUTH2_URL, appId, appSecret, code);
        String result = HttpUtil.get(requestUrl, CharsetUtil.CHARSET_UTF_8);
        logger.info("公众号登录：" + result);
        return JSONObject.parseObject(result, WeiXinOauth2Token.class);
    }
}
